package org.dev.hi.hiui.refresh;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.Scroller;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.dev.hi.library.log.HiLog;

public
/**
 * Author WenPing 
 * CreateTime 2021/3/31.
 * Description:
 */

class HiRefreshLayout extends FrameLayout implements HiRefresh {

    private static final String TAG = HiRefreshLayout.class.getSimpleName();

    private HiOverView.HirefreshState state;

    private GestureDetector gestureDetector;

    private AutoScroller autoScroller;

    private HiRefreshListener hiRefreshListener;

    protected HiOverView hiOverView;

    //最后滑动的y轴距离
    private int lastY;

    //刷新时是否禁止滚动
    private boolean disableRefreshScroll;

    public HiRefreshLayout(@NonNull Context context) {
        super(context);
        init();
    }

    public HiRefreshLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public HiRefreshLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        gestureDetector = new GestureDetector(getContext(), hiGestureDetector);
        autoScroller = new AutoScroller();
    }

    /**
     * return false 和return true 什么意思
     */
    private HiGestureDetector hiGestureDetector = new HiGestureDetector() {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if (Math.abs(distanceX) > Math.abs(distanceY)
                    || hiRefreshListener != null && !hiRefreshListener.enableRefresh()) {
                //横向滑动，或刷新被禁止，不处理
                return false;
            }
            if (disableRefreshScroll && state == HiOverView.HirefreshState.STATE_REFRESH) {
                //刷新时，禁止滑动；true 消费这个事件
                return true;
            }

            View head = getChildAt(0);
            View child = HiScrollUtil.findScrollableChild(HiRefreshLayout.this);
            if (HiScrollUtil.childScrolled(child)) {
                //如果列表发生了滚动，就不做处理
                return false;
            }
            //没有刷新，或者没有达到可刷新的距离；且头部已经划出下拉
            if ((state != HiOverView.HirefreshState.STATE_REFRESH
                    || head.getBottom() <= hiOverView.mPullRefreshHeight) && (
                    head.getBottom() > 0 || distanceY <= 0.0F)) {
                //还在 滑动中，没有松手
                if (state != HiOverView.HirefreshState.STATE_OVER_RELEASE) {
                    int speed;
                    //计算阻尼;这句是？什么意思？
                    if (child.getTop() < hiOverView.mPullRefreshHeight) {
                        speed = ((int) (lastY / hiOverView.minDamp));
                    } else {
                        speed = ((int) (lastY / hiOverView.maxDamp));
                    }
                    //如果正在刷新状态，就不允许在滑动中改变状态
                    boolean bool = moveDown(speed, true);
                    lastY = (int) -distanceY;
                    return bool;
                } else {
                    return false;
                }
            }else {
                return false;
            }
        }
    };

    @Override
    public void setDisableRefreshScroll(boolean disableRefreshScroll) {
        this.disableRefreshScroll = disableRefreshScroll;
    }

    /**
     * 刷新完成要恢复到初始化刷新的状态和位置
     */
    @Override
    public void refreshFinished() {
        View head = getChildAt(0);
        HiLog.i(TAG, "refreshFinished head-bottom:" + head.getBottom());
        hiOverView.onFinish();
        hiOverView.setState(HiOverView.HirefreshState.STATE_INIT);
        //这是?意思
        int bottom = head.getBottom();
        Log.e(TAG, "bottom:" + bottom);
        if (bottom > 0) {
            //如果头部的值大于0，要恢复
            recover(bottom);
        }
        // 重置状态为 初始化状态
        state = HiOverView.HirefreshState.STATE_INIT;
    }

    @Override
    public void setRefreshListener(HiRefreshListener hiRefreshListener) {
        this.hiRefreshListener = hiRefreshListener;
    }

    /**
     * add 刷新的效果到第一个元素
     * @param hiOverView
     */
    @Override
    public void setRefreshOverView(HiOverView hiOverView) {
        if (this.hiOverView != null) {
            removeView(hiOverView);
        }
        //为什么要使用match_parent的高度?
        this.hiOverView = hiOverView;
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        addView(hiOverView, 0, layoutParams);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //消费事件
        if (!autoScroller.isFinished) {
            return false;
        }

        View head = getChildAt(0);
        if (ev.getAction() == MotionEvent.ACTION_UP ||
                ev.getAction() == MotionEvent.ACTION_CANCEL||
                //松开手
                ev.getAction() == MotionEvent.ACTION_POINTER_INDEX_MASK) {
            if (head.getBottom() > 0) {
                //当前是不是刷新状态就recover
                if (state != HiOverView.HirefreshState.STATE_REFRESH) {
                    recover(head.getBottom());
                    return false;
                }
            }
            lastY = 0;
        }

        boolean consumed = gestureDetector.onTouchEvent(ev);
        HiLog.i(TAG, "gesture consumed:" + consumed);
        if ((consumed ||
                (state != HiOverView.HirefreshState.STATE_INIT &&
                        state != HiOverView.HirefreshState.STATE_REFRESH))
                && head.getBottom() != 0) {
            //让父类接受不到真实的事件
            ev.setAction(MotionEvent.ACTION_CANCEL);
            //直接 return true 可以?
            return super.dispatchTouchEvent(ev);
        }
        if (consumed) {
            return true;
        } else {
            return super.dispatchTouchEvent(ev);
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        //定义head和child的排列位置
        View head = getChildAt(0);
        View child = getChildAt(1);
        if (head != null && child != null) {
            HiLog.i(TAG, "onlayout-head.height:" + head.getMeasuredHeight());
            int childTop = child.getTop();
            //如果是刷新状态
            if (state == HiOverView.HirefreshState.STATE_REFRESH) {
                head.layout(0, hiOverView.mPullRefreshHeight - head.getMeasuredHeight(),
                        right, hiOverView.mPullRefreshHeight);
                child.layout(0, hiOverView.mPullRefreshHeight, right, child.getMeasuredHeight() + hiOverView.mPullRefreshHeight);
            } else {
                //不是刷新状态
                head.layout(0, childTop - head.getMeasuredHeight(), right, childTop);
                child.layout(0, childTop, right, childTop + child.getMeasuredHeight());
            }
            View other;
            //为什么从other开始
            for (int i = 2; i < getChildCount(); i++) {
                other = getChildAt(i);
                other.layout(0, top, right, bottom);
            }
            HiLog.i(TAG, "onlayout-head.bottom:" + head.getBottom());
        }
    }

    /**
     * 根据偏移量移动header与child
     *
     * @param offsetY 偏移量
     * @param nonAuto 是否非自动滚动触发
     * @return
     */
    private boolean moveDown(int offsetY, boolean nonAuto) {
        HiLog.i("mTag", "changeState:" + nonAuto);
        View head = getChildAt(0);
        View child = getChildAt(1);
        //child的高度
        int childTop = child.getTop() + offsetY;

        HiLog.i("-----", "moveDown head-bottom:" + head.getBottom() + ",child.getTop():" + child.getTop() + ",offsetY:" + offsetY);
        //异常情况
        if (childTop <= 0) {
            HiLog.i(TAG, "child.top < =0,state:" + state);
            offsetY = -child.getTop();
            //移动head和child的位置，到原始位置
            //这个api什么意思？
            head.offsetTopAndBottom(offsetY);
            child.offsetTopAndBottom(offsetY);
            //想想为什么？
        } else if (state == HiOverView.HirefreshState.STATE_REFRESH
                && childTop > hiOverView.mPullRefreshHeight) {
            return false;
            //还没超出刷新距离
        } else if (childTop <= hiOverView.mPullRefreshHeight) {
            if (hiOverView.getState() != HiOverView.HirefreshState.STATE_VISIBLE && nonAuto) {
                hiOverView.onVisible();
                hiOverView.setState(HiOverView.HirefreshState.STATE_VISIBLE);
            }
            head.offsetTopAndBottom(offsetY);
            child.offsetTopAndBottom(offsetY);
            if (childTop == hiOverView.mPullRefreshHeight && state == HiOverView.HirefreshState.STATE_OVER_RELEASE) {
                HiLog.i(TAG, "refresh,childTop:" + childTop);
                refresh();
            }
        }else {
            if (hiOverView.getState() != HiOverView.HirefreshState.STATE_OVER && nonAuto) {
                //超出刷新位置
                hiOverView.onOver();
                hiOverView.setState(HiOverView.HirefreshState.STATE_OVER_RELEASE);
            }
            head.offsetTopAndBottom(offsetY);
            child.offsetTopAndBottom(offsetY);
        }

        if (hiOverView != null) {
            hiOverView.onScroll(head.getBottom(), hiOverView.mPullRefreshHeight);
        }
        return true;
    }

    /**
     * 刷新方法
     */
    private void refresh() {
        if (hiRefreshListener != null) {
            state = HiOverView.HirefreshState.STATE_REFRESH;
            hiOverView.onRefresh();
            hiOverView.setState(HiOverView.HirefreshState.STATE_REFRESH);
            hiRefreshListener.onRefresh();
        }
    }

    /**
     *
     * @param dis
     */
    private void recover(int dis) {
        //刷新中
        if (hiRefreshListener != null && dis > hiOverView.mPullRefreshHeight) {
            autoScroller.recover(dis - hiOverView.mPullRefreshHeight);
            state = HiOverView.HirefreshState.STATE_OVER_RELEASE;
        } else {
            autoScroller.recover(dis);
        }
    }

    /**
     * 借助Scroller实现视图的自动滚动
     * https://juejin.im/post/5c7f4f0351882562ed516ab6
     */
    private class AutoScroller implements Runnable {

        private Scroller scroller;
        private int lastY;
        private boolean isFinished;

        public AutoScroller() {
            scroller = new Scroller(getContext(), new LinearInterpolator());
            isFinished = true;
        }

        @Override
        public void run() {
            //r如果还没滚动完成就下拉移动到位置
            if (scroller.computeScrollOffset()) {
                moveDown(lastY - scroller.getCurrY(), false);
                lastY = scroller.getCurrY();
                post(this);
            } else {
                removeCallbacks(this);
                isFinished = true;
            }
        }

        /**
         * 恢复到位置
         * @param dis
         */
        void recover(int dis) {
            if (dis <= 0) {
                return;
            }
            removeCallbacks(this);
            lastY = 0;
            isFinished = false;
            scroller.startScroll(0, 0,0, dis, 300);
            post(this);
        }

        boolean isFinished() {
            return isFinished;
        }

    }


}

